package com.ss.plugins.ws.collect.api.impl;


import com.ss.plugins.ws.collect.api.WsSessionList;
import com.ss.plugins.ws.collect.model.SessionBean;
import lombok.extern.slf4j.Slf4j;

import javax.websocket.Session;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 多页面SessionList
 *  就是一个客户端(相同的唯一属性)可以进行多个连接
 * @author xia17
 * @description: TODO
 * @date 2019/5/11 15:29
 */
@Slf4j
public class MoreSessionList<T extends SessionBean> implements WsSessionList<T> {

    /**
     * 存储自定义SessionBean 的容器
     */
    private Map<T, List<T>> sessions = new HashMap<>();

    /**
     * 判断是否包含，
     * @param sessionBean sessionBean对象
     * @return 包含取出对应List,不包含则返回null
     */
    @Override
    public synchronized boolean contain(T sessionBean) {
        return this.sessions.keySet().stream().anyMatch(sessionBean::myEquals);
    }

    /**
     * 添加一个Session
     * @param sessionBean 添加的Session对象
     * @return 成功返回true
     */
    @Override
    public synchronized boolean add(T sessionBean){
        //判空
        if (sessionBean.getSession()==null){
            log.error("添加失败：传入的moreSessionBean值异常");
            throw new RuntimeException("添加失败：传入的moreSessionBean值异常");
        }
        //判断是否包含
        List<T> contain = this.getSessionBeanList(sessionBean);
        //包含则往取出的List加上去
        if (contain!=null){
            if (contain.stream().anyMatch(e->sessionBean.getSession().getId().equals(e.getSession().getId()))){
                log.error("添加失败，该session已经存在容器中、");
                return false;
            }
            contain.add(sessionBean);
            return true;
        }
        //不包含则新建一个key
        List<T> list = new LinkedList<>();
        list.add(sessionBean);
        //强制类型转换
        sessions.put((T) sessionBean.copyOnlyAttribute(),list);
        return true;
    }

    /**
     * 移除一个客户端
     * @param sessionBean 自定义SessionBean
     * @return  成功返回true
     */
    @Override
    public synchronized boolean remove(T sessionBean) {
        List<T> contain = this.getSessionBeanList(sessionBean);
        if (contain==null){
            System.out.println("移除失败：应为没有这个连接");
            log.error("移除失败：应为没有这个连接");
            return false;
        }
        List<Session> session = this.getSession(sessionBean);
        //移除前先关闭所有连接
        for (Session session1 : session) {
            try {
                session1.close();
            } catch (IOException e) {
                log.error("连接关闭失败");
                System.out.println("连接关闭失败");
            }
        }
        sessions.remove(this.getMapKey(sessionBean));
        return true;
    }

    /**
     * 通过Ws 的Session 移除一个SessionBean
     * @param session 过Ws 的Session
     * @return 成功true
     */
    @Override
    public synchronized boolean remove(Session session) {
        //遍历Key
        for (T sessionBeanKey : sessions.keySet()) {
            //获取session集合
            List<T> sessionBeans = this.sessions.get(sessionBeanKey);
            //移除
            if (sessionBeans!=null){
                for (T sessionBean : sessionBeans) {
                    if (sessionBean.getSession().getId().equals(session.getId())){
                        try {
                            session.close();
                        } catch (IOException e) {
                            log.error("连接已关闭");
                        }
                        log.info("执行删除操作");
                        sessionBeans.remove(sessionBean);
                        //删除Map中的key
                        if (sessionBeans.size()==0){
                            this.sessions.remove(sessionBeanKey);
                        }
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * 返回客户端数量 , 不同唯一属性的数量
     * @return int
     */
    @Override
    public int clientSize() {
        return this.sessions.size();
    }

    /**
     * 返回session数量 , 多少个连接
     * @return int
     */
    @Override
    public int sessionSize(){
        int result = 0;
        for (List<T> value : this.sessions.values()) {
            result += value.size();
        }
        return result;
    }


    /**
     * 获取所有Session
     * @return Session
     */
    @Override
    public List<Session> getAllSession() {
        return this.sessions.values().stream().
                flatMap(List::stream)
                .map(SessionBean::getSession)
                .collect(Collectors.toList());
    }

    /**
     * 返回一个客户端对应的Session
     * @param sessionBean sessionBean
     * @return 集合
     */
    @Override
    public List<Session> getSession(T sessionBean) {
        return this.sessions.keySet().stream()
                .filter(sessionBean::myEquals)
                .flatMap(e->this.sessions.get(e).stream())
                .map(SessionBean::getSession)
                .collect(Collectors.toList());
    }

    /**
     * 根据Ws 的 session 获取一个包装session的Bean（带有自己数据的）
     * @param session Ws Session
     * @return 不存在返回null
     */
    @Override
    public Optional<T> getSessionBean(Session session) {
        return this.sessions.values().stream()
                .flatMap(List::stream)
                .filter(e->session.getId().equals(e.getSession().getId()))
                .findAny();
    }

    @Override
    public List<T> getSessionBeanList(T sessionBean) {
        T t = this.getMapKey(sessionBean);
        if (t==null){
            return null;
        }
        return this.sessions.get(t);
    }



    /**
     * 根据SessionBean 获取SessionBean数据
     * @param sessionBean 自定义SessionBean
     * @return 返回一个Object ,单页面是个对象，多页面是个集合
     */
    @Deprecated
    @Override
    public Optional<T> getSessionBean(SessionBean sessionBean){
        throw new RuntimeException("未实现此方法，请使用getSessionBeanList()");
    }


    /**
     * 获取map中的key
     * @param sessionBean 唯一对象的标志
     * @return 找到返回对象，未找到返回null
     */
    private T getMapKey(T sessionBean){
        return this.sessions.keySet().stream()
                .filter(sessionBean::myEquals)
                .findAny().orElse(null);
    }

}